package com.queclink.ycm.common.utils;

import org.springframework.stereotype.Component;

/**
 * @author jim.li
 * @email jim.li@queclink.com
 * @date 2022-02-10 15:23:00
 */
@Component
public class MD5Utils {
    long[] groups = null;

//    String resultMessage = "";

    static final long A = 412501297L;

    static final long B = 1454103806L;

    static final long C = 2280635085L;

    static final long D = 629577828L;

//    private long[] result = new long[] { 412501297L, 1454103806L, 2280635085L, 629577828L };

    static final long[][] T = new long[][] { {
            -680876936L, -389564586L, 606105819L, -1044525330L, -176418897L, 1200080426L, -1473231341L, -45705983L, 1770035416L, -1958414417L,
            -42063L, -1990404162L, 1804603682L, -40341101L, -1502002290L, 1236535329L }, {
            -165796510L, -1069501632L, 643717713L, -373897302L, -701558691L, 38016083L, -660478335L, -405537848L, 568446438L, -1019803690L,
            -187363961L, 1163531501L, -1444681467L, -51403784L, 1735328473L, -1926607734L }, {
            -378558L, -2022574463L, 1839030562L, -35309556L, -1530992060L, 1272893353L, -155497632L, -1094730640L, 681279174L, -358537222L,
            -722521979L, 76029189L, -640364487L, -421815835L, 530742520L, -995338651L }, {
            -198630844L, 1126891415L, -1416354905L, -57434055L, 1700485571L, -1894986606L, -1051523L, -2054922799L, 1873313359L, -30611744L,
            -1560198380L, 1309151649L, -145523070L, -1120210379L, 718787259L, -343485551L } };

    static final int[][] k = new int[][] { {
            0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
            10, 11, 12, 13, 14, 15 }, {
            1, 6, 11, 0, 5, 10, 15, 4, 9, 14,
            3, 8, 13, 2, 7, 12 }, {
            5, 8, 11, 14, 1, 4, 7, 10, 13, 0,
            3, 6, 9, 12, 15, 2 }, {
            0, 7, 14, 5, 12, 3, 10, 1, 8, 15,
            6, 13, 4, 11, 2, 9 } };

    static final int[][] S = new int[][] { { 7, 12, 17, 22 }, { 5, 9, 14, 20 }, { 4, 11, 16, 23 }, { 6, 10, 15, 21 } };

    private static long g(int paramInt, long paramLong1, long paramLong2, long paramLong3) {
        switch (paramInt) {
            case 0:
                return paramLong1 & paramLong2 | (paramLong1 ^ 0xFFFFFFFFFFFFFFFFL) & paramLong3;
            case 1:
                return paramLong1 & paramLong3 | paramLong2 & (paramLong3 ^ 0xFFFFFFFFFFFFFFFFL);
            case 2:
                return paramLong1 ^ paramLong2 ^ paramLong3;
            case 3:
                return paramLong2 ^ (paramLong1 | paramLong3 ^ 0xFFFFFFFFFFFFFFFFL);
        }
        return 0L;
    }

    public static String start(String paramString) {
        byte[] arrayOfByte1 = paramString.getBytes();
        String resultMessage = "";
        long[] result = new long[] { 412501297L, 1454103806L, 2280635085L, 629577828L };
        int i = arrayOfByte1.length;
        long l = (i << 3);
        int j = i / 64;
        int k;
        for (k = 0; k < j; k++)
            H(divide(arrayOfByte1, k * 64), result);
        k = i % 64;
        byte[] arrayOfByte2 = new byte[64];
        int m;
        for (m = 0; m < k; m++)
            arrayOfByte2[m] = arrayOfByte1[i - k + m];
        if (k <= 56) {
            if (k < 56) {
                arrayOfByte2[k] = Byte.MIN_VALUE;
                for (m = 1; m < 56 - k; m++)
                    arrayOfByte2[k + m] = 0;
            }
            for (m = 0; m < 8; m++) {
                arrayOfByte2[56 + m] = (byte)(int)(l & 0xFFL);
                l >>= 8L;
            }
            H(divide(arrayOfByte2, 0), result);
        } else {
            arrayOfByte2[k] = Byte.MIN_VALUE;
            for (m = k + 1; m < 64; m++)
                arrayOfByte2[m] = 0;
            H(divide(arrayOfByte2, 0), result);
            for (m = 0; m < 56; m++)
                arrayOfByte2[m] = 0;
            for (m = 0; m < 8; m++) {
                arrayOfByte2[56 + m] = (byte)(int)(l & 0xFFL);
                l >>= 8L;
            }
            H(divide(arrayOfByte2, 0), result);
        }
        for (m = 0; m < 4; m++) {
//            this.resultMessage += String.format("%02x", new Object[] { Long.valueOf(this.result[m] & 0xFFL) }) + String.format("%02x", new Object[] { Long.valueOf((this.result[m] & 0xFF00L) >> 8L) }) + String.format("%02x", new Object[] { Long.valueOf((this.result[m] & 0xFF0000L) >> 16L) }) + String.format("%02x", new Object[] { Long.valueOf((this.result[m] & 0xFFFFFFFFFF000000L) >> 24L) });
            resultMessage += String.format("%02x", new Object[] { Long.valueOf(result[m] & 0xFFL) }) + String.format("%02x", new Object[] { Long.valueOf((result[m] & 0xFF00L) >> 8L) }) + String.format("%02x", new Object[] { Long.valueOf((result[m] & 0xFF0000L) >> 16L) }) + String.format("%02x", new Object[] { Long.valueOf((result[m] & 0xFFFFFFFFFF000000L) >> 24L) });
        }
        return resultMessage;
    }

    private static long[] divide(byte[] paramArrayOfbyte, int paramInt) {
        long[] arrayOfLong = new long[16];
        for (byte b = 0; b < 16; b++)
            arrayOfLong[b] = byte2unsign(paramArrayOfbyte[4 * b + paramInt]) | byte2unsign(paramArrayOfbyte[4 * b + 1 + paramInt]) << 8L | byte2unsign(paramArrayOfbyte[4 * b + 2 + paramInt]) << 16L | byte2unsign(paramArrayOfbyte[4 * b + 3 + paramInt]) << 24L;
        return arrayOfLong;
    }

    public static long byte2unsign(byte paramByte) {
        return (paramByte < 0) ? (paramByte & 0xFF) : paramByte;
    }
    private static void H(long[] paramArrayOflong, long[] result) {
        long l1 = result[0], l2 = result[1], l3 = result[2], l4 = result[3];
        byte b;
        for (b = 0; b < 4; b++) {
            for (byte b1 = 0; b1 < 16; b1++) {
                result[0] = result[0] + (g(b, result[1], result[2], result[3]) & 0xFFFFFFFFL) + paramArrayOflong[k[b][b1]] + T[b][b1];
                result[0] = result[1] + ((result[0] & 0xFFFFFFFFL) << S[b][b1 % 4] | (result[0] & 0xFFFFFFFFL) >>> 32 - S[b][b1 % 4]);
                long l = result[3];
                result[3] = result[2];
                result[2] = result[1];
                result[1] = result[0];
                result[0] = l;
            }
        }
        result[0] = result[0] + l1;
        result[1] = result[1] + l2;
        result[2] = result[2] + l3;
        result[3] = result[3] + l4;
        for (b = 0; b < 4; b++)
            result[b] = result[b] & 0xFFFFFFFFL;
    }

//    private void H(long[] paramArrayOflong, long[] result) {
//        long l1 = this.result[0], l2 = this.result[1], l3 = this.result[2], l4 = this.result[3];
//        byte b;
//        for (b = 0; b < 4; b++) {
//            for (byte b1 = 0; b1 < 16; b1++) {
//                this.result[0] = this.result[0] + (g(b, this.result[1], this.result[2], this.result[3]) & 0xFFFFFFFFL) + paramArrayOflong[k[b][b1]] + T[b][b1];
//                this.result[0] = this.result[1] + ((this.result[0] & 0xFFFFFFFFL) << S[b][b1 % 4] | (this.result[0] & 0xFFFFFFFFL) >>> 32 - S[b][b1 % 4]);
//                long l = this.result[3];
//                this.result[3] = this.result[2];
//                this.result[2] = this.result[1];
//                this.result[1] = this.result[0];
//                this.result[0] = l;
//            }
//        }
//        this.result[0] = this.result[0] + l1;
//        this.result[1] = this.result[1] + l2;
//        this.result[2] = this.result[2] + l3;
//        this.result[3] = this.result[3] + l4;
//        for (b = 0; b < 4; b++)
//            this.result[b] = this.result[b] & 0xFFFFFFFFL;
//    }
}

